今天來說 Ktor 自動化測試的部分
我們可以參考 https://openaidoc.org/zh-Hant/ktor/server-testing 這份文件
Ktor 的自動化測試使用的是 kotlin.test 這個框架
package com.example
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.server.testing.*
import kotlin.test.Test
import kotlin.test.assertEquals
class ApplicationTest {
@Test
fun testRoot() =
testApplication {
application {
module()
}
client.get("/").apply {
assertEquals(HttpStatusCode.OK, status)
}
}
}
使用 testApplication()
建立測試用的 ApplicationTestBuilder
之後,
呼叫 application.module()
將對應的所有套件全部安裝好,包含路由也一併在這時候引入
安裝好之後就可以使用 ApplicationTestBuilder
內的 client
存取路由,
之後就可以對回傳內容作 assert
了。
如果要測試 POST 路徑也可以,我們可以使用 header()
和 setBody()
設置 POST 請求的內容
@Test
fun testPost() = testApplication {
application {
module()
}
val response = client.post("/signup") {
header(HttpHeaders.ContentType, ContentType.Application.FormUrlEncoded.toString())
setBody(listOf("username" to "JetBrains", "email" to "example@jetbrains.com", "password" to "foobar", "confirmation" to "foobar").formUrlEncode())
}
assertEquals("The 'JetBrains' account is created", response.bodyAsText())
}
參考 https://openaidoc.org/zh-Hant/ktor/client-testing
假設我們有撰寫自定義的 Client 物件
@Serializable
data class IpResponse(val ip: String)
class ApiClient(engine: HttpClientEngine) {
private val httpClient = HttpClient(engine) {
install(ContentNegotiation) {
json()
}
}
suspend fun getIp(): IpResponse = httpClient.get("https://api.ipify.org/?format=json").body()
}
如果我們要測試 Client 連線狀況,而不實際的進行連線
我們可以使用 Ktor 的 ktor-client-mock
首先,我們先安裝測試用套件
testImplementation("io.ktor:ktor-client-mock:3.3.0")
然後測試內就可以使用了
class ApiClientTest {
@Test
fun sampleClientTest() {
runBlocking {
val mockEngine = MockEngine { request ->
respond(
content = ByteReadChannel("""{"ip":"127.0.0.1"}"""),
status = HttpStatusCode.OK,
headers = headersOf(HttpHeaders.ContentType, "application/json")
)
}
val apiClient = ApiClient(mockEngine)
Assert.assertEquals("127.0.0.1", apiClient.getIp().ip)
}
}
}
由於 Ktor 核心的功能其實很精簡,針對 Ktor 本身的測試功能也非常精簡。
基本上只需要,也只能針對請求的內容和回應的內容進行判斷。其他的功能都隸屬於其他的框架或套件進行測試。
今天的部分就到這邊,我們明天見!